As bases e gráficos usados abaixo foram retirados da segunda oficina.
library(tidyverse)
library(plotly)
performance = read_csv('bases/student_habits_performance.csv')
performance = performance %>% filter(gender!='Other')
O ggplotly() é uma função do pacote plotly
que converte um gráfico criado com ggplot2 em um gráfico interativo do
Plotly.
Principais parâmetros do ggplotly():
p : O objeto ggplot que será convertido para
Plotly.
tooltip : Define quais variáveis aparecerão no
tooltip (dica de informação ao passar o mouse).
dynamicTicks : Se TRUE, os eixos se ajustam
dinamicamente ao zoom.
Peguemos de exemplo um gráfico feito na segunda oficina do projeto DataViz.
graf1 = performance %>%
ggplot(aes(x = study_hours_per_day, y = exam_score, color = gender)) +
geom_point(alpha = 0.5)+
geom_smooth(method='lm',se = F)+
scale_y_continuous(breaks = seq(0, 100, 20))+
scale_color_manual(values = c("Red","Blue"),
labels = c("Mulher","Homem"))+ # mudando o nome das categorias
labs(x = "Horas de Estudo Diário", y = "Nota" ,color = "" ,
title = "Relação entre Horas de Estudo e Nota",
subtitle = "Student Habits vs Academic Performance: A Simulated Study",
caption = "Fonte: https://www.kaggle.com/datasets") +
theme_classic()
graf1
ggplotly(graf1)
Perceba que detalhes como subtítulo, a legenda e os textos estão
diferentes. Quando a função ggplotly() é utilizada, nem
todas as modificações feitas anteriormente serão mantidas.
Uma forma de solucionar esse problema é usando a função
layout() do plotly que controla o aspecto
geral do gráfico, como títulos, eixos, legendas, margens e
anotações.
# transformando os dados antes de plotar
performance = performance %>%
mutate(gender = case_when(
gender == "Female" ~ "Mulher",
gender == "Male" ~ "Homem",
TRUE ~ as.character(gender)
))
# gráfico modificado
graf1_mod = performance %>%
ggplot(aes(x = study_hours_per_day, y = exam_score, color = gender)) +
geom_point(alpha = 0.5,
aes(text = paste0("Horas de Estudo: ", study_hours_per_day,
"<br>",
"Nota: ", exam_score,
"<br>",
"Sexo: ", gender,
"<br>",
"Horas de Sono: ", sleep_hours)))+
geom_smooth(method='lm',se = F)+
scale_y_continuous(breaks = seq(0, 100, 20))+
scale_color_manual(values = c("Red","Blue"))+ # mudando o nome das categorias
labs(x = "Horas de Estudo Diário", y = "Nota" ,color = "" ,
title = "Relação entre Horas de Estudo e Nota") +
theme_classic()
ggplotly(graf1_mod,
tooltip = "text",# a informação do hover será a do text do geom_point
dynamicTicks = TRUE)%>% # ajuste dos eixos
layout(hoverlabel=list(bgcolor = "#ffffff"), # definindo cor do fundo do hover
title = "<b>Relação entre Horas de Estudo e Nota</b><br><sub>Student Habits vs Academic Performance: A Simulated Study</sub>", # título e subtítulo
legend = list(
title = list(text = "Sexo"), # título da legenda
x = 0.8, # posição da legenda no layout
y = 0.1,
orientation = "v" # categorias na vertical
)
)
Shapes são arquivos que contém coordenadas geográficas que podem ser
transformadas em mapas. Esses arquivos podem ser retirados do site do
Instituto Brasileiro de Geografia e Estatística (IBGE) ou do pacote
geobr por exemplo.
Para importar shapefile, utiliza-se a função st_read()
do pacote sf. Para que a leitura do arquivo shapefile
funcione corretamente, todos os arquivos auxiliares devem estar na mesma
pasta do diretório.
.shp - O arquivo que armazena a geometria dos elementos (obrigatório);
.shx - O índice da geometria dos elementos (obrigatório);
.dbf - A tabela de atributos em formato dBASE, que contém informações descritivas dos elementos (obrigatório);
Outros arquivos opcionais podem fornecer informações adicionais como projeção e codificação de caracteres.
if(!require("sf")) install.packages("sf")
library(sf)
#lendo o shapefile dos municípios do Rio de Janeiro
RJshape = st_read('shapes/RJ_Municipios_2024/RJ_Municipios_2024.shp', options = "ENCODING=UTF-8")
options: ENCODING=UTF-8
Reading layer `RJ_Municipios_2024' from data source
`D:\uff\DataViz\shapes\RJ_Municipios_2024\RJ_Municipios_2024.shp'
using driver `ESRI Shapefile'
Simple feature collection with 92 features and 15 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -44.88932 ymin: -23.36893 xmax: -40.95794 ymax: -20.76321
Geodetic CRS: SIRGAS 2000
# Forma alternativa:
if(!require("geobr")) install.packages("geobr")
library(geobr)
RJshape = read_municipality(code_muni = "RJ", year = 2024)
# Filtrar apenas Niterói:
nit_shape <- RJshape %>%
filter(name_muni == "Niterói")
Existem diversas maneiras de criar mapas no R, uma delas é através da
função geom_sf() do pacote ggplot2. A função
detecta a informação geométrica dos objetos sf para
desenhar o mapa.
# lendo o shapefile dos bairros de Niterói
bairros = st_read("shapes/BairrosNit/Limite_de_Bairros.shp")
Reading layer `Limite_de_Bairros' from data source
`D:\uff\DataViz\shapes\BairrosNit\Limite_de_Bairros.shp' using driver `ESRI Shapefile'
Simple feature collection with 52 features and 6 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 690971.9 ymin: 7456344 xmax: 710984.7 ymax: 7471474
Projected CRS: SIRGAS 2000 / UTM zone 23S
# Mapa vazio
ggplot(bairros) + geom_sf()
Os dados espaciais podem vir em diversos sistemas de referência de coordenadas (CRS). Então, até mesmo antes de plotar os mapas, precisamos verificar se as coordenadas dos dados possuem o mesmo CRS. Caso contrário, as coordenadas precisam ser transformadas para evitar problemas de desalinhamento, distorção, erros de projeção,etc.
A função utilizada para transformar coordenadas é
st_transform(). Basta inserir o objeto sf e o
crs de interesse como argumentos da função.
# lendo pontos
escolas = read_csv('bases/Escolas_Municipais_de_Ensino_Fundamental.csv')
escolas
# criando objeto sf com as coordenadas em UTM
pontos_utm = st_as_sf(
escolas, #
coords = c("X", "Y"),
crs = 31983 # EPSG
)
#transformando dados em UTM para lat/long
pontos_latlong = st_transform(pontos_utm, crs = 4674)
#matriz com coordenadas
coordenadas = st_coordinates(pontos_latlong)
#adicionando colunas com as coordenadas no data.frame pontos_nit
pontos_nit = escolas %>% mutate(LONGITUDE = coordenadas[,1],
LATITUDE = coordenadas[,2])
É possível apresentar mais de uma informação geométrica em um único mapa. Existem duas formas de plotar os pontos no mapa:
geom_sf() com o objeto sf
geom_point() com as coordenadas nos eixos
# filtrando apenas o município de Niterói
nit_shape = RJshape %>%
filter(NM_MUN == "Niterói")
# com geom_point():
ggplot(nit_shape)+
geom_sf()+
geom_point(data = pontos_nit,aes(x = LONGITUDE, y = LATITUDE))+
theme_minimal()
ggplot(bairros)+
geom_sf()+
geom_point(data = pontos_nit,aes(x = X, y = Y))+
theme_minimal()
Perceba que ao usar nit_shape (que está em graus) os pontos são mapeados através das colunas LONGITUDE e LATITUDE que correspondem às coordenadas em graus. Quando usamos bairros, os pontos são mapeados através de X e Y que correpondem às coordenadas UTM.
# com geom_sf():
ggplot()+
geom_sf(data = bairros)+
geom_sf(data = pontos_utm) +
theme_minimal()
A forma de modificar a estética do mapa é a mesma para todos os
geoms.
ggplot()+
geom_sf(data = bairros,fill='white')+ # plotagem do município de Niterói
geom_sf(data = pontos_utm, # plotagem dos pontos
aes(col=tx_turno))+ # pontos coloridos de acordo com o turno
facet_wrap(~tx_regiao)+ # facetas por região
labs(color = 'Turno')+
theme_minimal()+
theme(legend.position = 'bottom') # legenda para baixo
Para apresentar observações de uma variável de interesse em uma
determinada área, é preciso integrar as informações da variável com a
geometria do shapefile através de um _join. Como a base
inicial é o shape, a base resultante precisa ter as mesmas linhas. A
variável link, que pode ser o nome ou código do local,
tem que estar presente em ambas as bases e precisa ser de classes
iguais.
# lendo a base de taxa de mortalidade bruta no RJ
taxaRJ = read_csv2('bases/taxa_mortRJ.csv',locale = locale(encoding = "latin1"))
# juntando as duas bases para formar um único objeto sf
taxa_shape = RJshape %>% left_join(taxaRJ,by = c('NM_MUN'='Município'))
Com a base integrada pronta, é possível plotar o mapa coroplético.
# taxa de mortalidade por município RJ
taxa_shape %>%
ggplot(aes(fill=Total)) +
geom_sf()+
labs(fill = 'Taxa')
De forma análoga aos gráficos vistos na segunda oficina, é possível
personalizar as cores dos polígonos dos mapas com funções
scale_fill_. No entanto, para inserir textos, de acordo com
objetos sf, utilize as funções geom_sf_text()
ou geom_sf_label() ao invés do
geom_text().
# taxa de mortalidade por município RJ
taxa_shape %>%
ggplot(aes(fill=Total)) +
geom_sf()+
scale_fill_gradient(name = "Taxa",
low = "white", # gradiente manual
high = "red")+
theme_minimal()
taxa_shape %>%
ggplot(aes(fill=Total)) +
geom_sf()+
scale_fill_viridis_c(name='Taxa',
option = "magma", # paletas modernas para variaveis contínuas
direction= -1)+ # invertendo a ordem das cores
theme_minimal()
taxa_shape %>%
ggplot(aes(fill=Total)) +
geom_sf()+
scale_fill_distiller(name = 'Taxa',
palette = "Blues", # paletas pré-definidas
trans = "reverse")+ # invertendo os valores
theme_minimal()
Outra forma de fazer mapas temáticos no R é usando as funções do
pacote tmap. Este pacote, além de criar mapas estáticos,
também é utilizado parar criar mapas interativos. As funções possuem uma
sintaxe simples, similar ao ggplot2.
# Instalando e carregando o pacote tmap
if (!require("tmap")) install.packages("tmap")
library(tmap)
Para plotar um mapa utilizando tmap, as funções
essenciais são:
tm_shape() : Define a camada espacial a ser
utilizada para plotar o mapa. O argumento deverá ser uma base de dados
com informação geoespacial.
tm_polygon() : Define os limites e preenche os
polígonos.
tm_borders() : Adiciona as bordas do mapa.
tm_fill() : Peenche a cor dos polígonos sem adição
da borda.
# Mapa inicial
tm_shape(shp = taxa_shape)+
tm_polygons()
# Outra maneira de plotar o mesmo mapa
tm_shape(shp = taxa_shape)+
tm_fill()+
tm_borders()
tmaptm_shape(shp = taxa_shape)+
tm_fill(col='Total',palette = 'Reds')+
tm_borders()
Existem várias formas (automáticas ou manuais) para preencher um mapa. Dentro da função utilizada para colorir o mapa, é possível utilizar os seguintes argumentos para customizá-lo da maneira que preferir:
style = pretty : Configuração padrão da função.
Arredonda os limites dos intervalos para números inteiros;
style = equal : Divide a variável em intervalos de
comprimentos iguais;
style = quantile : Divide a variável em
quantis;
style = jenks : Identifica grupos com valores
semelhantes e maximiza a diferença entre eles;
style = cont : Exibe várias cores em uma paleta
contínua;
style = cat : Colore cada categoria individualmente
para dados categóricos;
n : Define o número de intervalos;
breaks : Forma manual de definir os
intervalos.
equal = tm_shape(shp = taxa_shape)+
tm_borders(col='gray10')+
tm_fill(col='Total',palette = 'Reds',style='equal')
quantile = tm_shape(shp = taxa_shape)+
tm_borders(col='gray10')+
tm_fill(col='Total',palette = 'Reds',style='quantile')
jenks = tm_shape(shp = taxa_shape)+
tm_borders(col='gray10')+
tm_fill(col='Total',palette = 'Reds',style='jenks')
cont = tm_shape(shp = taxa_shape)+
tm_borders(col='gray10')+
tm_fill(col='Total',palette = 'Reds',style='cont')
n = tm_shape(shp = taxa_shape)+
tm_borders(col='gray10')+
tm_fill(col='Total',palette = 'Reds', n = 4)
breaks = tm_shape(shp = taxa_shape)+
tm_borders(col='gray10')+
tm_fill(col='Total',palette = 'Reds',breaks = c(0,3,6,9,max(taxa_shape$Total)))
tmap_arrange(equal,quantile,jenks,cont,n,breaks, ncol =3)
Outras funções úteis do tmap para detalhar os mapas:
tm_lines(): Adiciona linhas ao mapa
tm_dots(): Adiciona pontos ao mapa
tm_text(): Adiciona rótulos de texto
tm_layout(): Personaliza o layout geral
tm_legend(): Controla a aparência da legenda
tm_scale_bar(): Adiciona uma barra de escala
tm_compass(): Adiciona uma rosa dos ventos
tm_bubbles(): Adiciona uma camada de bolhas
# Exemplo de mapa com alguma das funções acima
tm_shape(shp = taxa_shape)+
tm_fill(col = c("Feminino","Masculino"),
palette = 'Blues')+
tm_borders()+
tm_layout(panel.labels = c("Feminino","Masculino"))+
tm_compass()+
tm_scale_bar()+
tm_layout(title = 'Taxa de mortalidade no RJ',
legend.position = c("left","top"))
# Com escalas iguais
tm_shape(shp = taxa_shape)+
tm_fill(col = c("Feminino","Masculino"),
palette = 'Blues',
title='Taxa')+
tm_borders()+
tm_layout(panel.labels = c("Feminino","Masculino"))+
tm_facets(free.scales = FALSE) +
tm_compass()+
tm_scale_bar()+
tm_layout(legend.position = c("left","top"))
tmap_mode()Para ativar interatividade em um mapa feito com o pacote
tmap,basta utilizar o comando
tmap_mode("view"). Caso prefira retornar ao modo estático,
use tmap_mode("plot").
# Modo interativo:
tmap_mode("view")
# Especificando as informações que aparecem nos popups
tm_shape(shp = taxa_shape) + tm_borders(col = "gray10") + tm_fill(col = "Total",
palette = "Reds", style = "cont", title = "Taxa", popup.vars = c(Município = "NM_MUN",
`Taxa total` = "Total", `Taxa feminina` = "Feminino", `Taxa masculina` = "Masculino",
`Área(km2)` = "AREA_KM2"), id = "NM_MUN") + tm_layout(title = "Taxa de mortalidade no RJ")